package impl

import (
	"context"
	"fmt"

	"gitee.com/go-kade/go12/vblog/apps/token"
	"gitee.com/go-kade/go12/vblog/apps/user"
	"gitee.com/go-kade/go12/vblog/conf"
	"gitee.com/go-kade/go12/vblog/exception"
	"gitee.com/go-kade/go12/vblog/ioc"
	"github.com/rs/xid"
	"gorm.io/gorm"
)

// var _ token.Service = &TokenServiceImpl{}
var _ token.Service = (*TokenServiceImpl)(nil)

type TokenServiceImpl struct {
	db *gorm.DB
	//这里需要依赖另一个业务领城：用户管理领城
	user user.Service
}

func NewTokenServiceImpl(UserServiceImpl user.Service) *TokenServiceImpl { //给db初始化
	// db, _ := gorm.Open(mysql.Open("root:cys000522@tcp(34.28.164.10:3306)/go12?charset=utf8mb4&parseTime=True&loc=Local"), &gorm.Config{})
	return &TokenServiceImpl{
		db: conf.C().MySQL.GetConn().Debug(),
		//user: UserServiceImpl,
		user: ioc.Controller().Get(user.AppName).(user.Service),
	}
}

// 导入这个包的时候，直接把这个对象 UserServiceImpL 注册给IocUserService ioc
// 注册user业务模块(业务模块的名称是user.AppName)的控制器
func init() {
	ioc.Controller().Registry(&TokenServiceImpl{})
}

// 定义对象的初始化
func (i *TokenServiceImpl) Init1() error {
	i.db = conf.C().MySQL.GetConn().Debug()
	i.user = ioc.Controller().Get(user.AppName).(user.Service)
	return nil
}

// 定义托管到Ioc里面的名称
func (i *TokenServiceImpl) Name() string {
	return token.AppName
}

// 登灵接口（额发Token)
func (i *TokenServiceImpl) Login(ctx context.Context, req *token.LoginRequst) (*token.Token, error) {
	//1.查询用户
	ureq := user.NewQueryUserRequestName(req.Username)
	u, err := i.user.QueryUser(ctx, ureq)
	if err != nil {
		if exception.IsNotFound(err) {
			// fmt.Println(exception.NewAuthFound("cccccccc").Error())
			return nil, exception.NewAuthFound("查询用户失败11")
		}
		return nil, err
	}

	//2.比对密码
	// fmt.Println("-----------------------1")
	err = u.CheckPassword(req.Password)
	if err != nil {
		return nil, exception.NewAuthFound("用户名或者密码不正确:%s", err)
	}
	// fmt.Println("-----------------------2")
	//3.颁发token
	tk := token.NewToken()
	tk.UserID = u.ID
	tk.UserName = u.Username

	switch i.db.WithContext(ctx).Where("username = ?", u.Username).First(tk).Error {
	case gorm.ErrRecordNotFound: //3.颁发token,保存token
		i.db.WithContext(ctx).Create(tk)
		// fmt.Println("----------------", tk)
		return tk, nil
	case nil: //4.更新token
		tk.AccessToken = tk.RefreshToken
		tk.RefreshToken = xid.New().String()
		i.db.Model(&token.Token{}).Where("username= ?", tk.UserName).Updates(tk)
		return tk, nil
	default:
		return tk, exception.NewAuthFound("错误异常")
	}
	// 避免同一个用户多次登灵
	// 5. 预发成功后 把之前的Token标记为失效，件业
}

// 退出登灵接口（销毁Token)
func (c *TokenServiceImpl) Logout(ctx context.Context, req *token.LoginOutRequst) error {
	tk := token.NewToken() //结构体先初始化，不然查询数据库会报空指针
	err := c.db.WithContext(ctx).Where("access_token = ?", req.AccessToken).Delete(tk).Error
	if err != nil {
		return exception.NewNotFound("token check failure")
	}
	return nil
}

// 校验Token 是给內部中间层使用 身份校验层
func (c *TokenServiceImpl) ValiateToken(ctx context.Context, req *token.ValiateToken) (*token.Token, error) {
	//1.查询token（谁颁发的）
	tk := token.NewToken() //结构体先初始化，不然查询数据库会报空指针
	err := c.db.WithContext(ctx).Where("access_token = ?", req.AccessToken).First(tk).Error
	if err != nil {
		return nil, exception.NewNotFound("token check failure")
	}
	//2.判断token的合法性
	if err := tk.IsExpired(); err != nil {
		return nil, err
	}
	// 补充用户信息, 只补充了用户的角色
	uDesc := user.NewQueryUserRequestID(fmt.Sprintf("%d", tk.UserID))
	u, err := c.user.QueryUser(ctx, uDesc)
	if err != nil {
		return nil, err
	}
	tk.Role = u.Role

	return tk, nil

}
